package gnssio

import (
	"dgo/goutils/dnet"
	"dgo/goutils/gis"
	"dgo/goutils/utils"
	"errors"
	"fmt"
	"strings"
	"time"
)

type CommTcpClient struct {
	flag       byte
	client     *dnet.ASyncTcpClient
	listeners  *utils.SafeList
	nmea       *gis.NMEA
	TimeOutSec int
	taskTimer  *time.Timer
}

func NewCommTcpClient(addr string, gga string) *CommTcpClient {
	rval := &CommTcpClient{
		flag:       0,
		client:     dnet.NewASyncTcpClient(),
		listeners:  utils.NewSafeList(),
		TimeOutSec: 30,
	}

	if len(gga) > 0 {
		m := gis.NewNMEA()
		m.ParseText(gga)
		rval.nmea = m
	}

	rval.client.SetAddress(addr)
	rval.client.UseQueueSend = false
	rval.client.OnRecvBuffer = rval.onRecvClientBuffer
	rval.client.OnConnected = rval.onConnected
	rval.client.OnDisconnected = rval.onDisconnected
	return rval
}

/*
**

	tcp://ip:port[/tagstr]
*/
func NewCommTcpClientFromCmd(cmdstr string) *CommTcpClient {
	if len(cmdstr) < 9 {
		return nil
	}

	ok, cmdstr := utils.CheckTrimPrefix(cmdstr, "tcp://")
	if !ok {
		return nil
	}

	strs := strings.SplitN(cmdstr, "/", 2)
	addr := strs[0]
	tagstr := ""
	if len(strs) == 2 {
		tagstr = strs[1]
	}

	return NewCommTcpClient(addr, tagstr)

}

func CreateTcpClientCommFromCmdLineFunc(args ...interface{}) (rval interface{}, err error) {
	if len(args) < 1 {
		return nil, errors.New("至少要传入一个参数")
	}
	cmdStr := args[0].(string)
	if len(cmdStr) == 0 {
		return nil, errors.New("创建TcpClient失败: 命令参数为空")
	}
	obj := NewCommTcpClientFromCmd(cmdStr)
	if obj == nil {
		return nil, errors.New(fmt.Sprintf("创建TcpClient失败: 命令参数(%s)非法", cmdStr))
	}
	return obj, nil
}

func (this *CommTcpClient) onConnected(sender *dnet.ASyncTcpClient) {
	this.listeners.ForEach(func(val interface{}) {
		val.(I_CommListener).OnConnect(this)
	})
}

func (this *CommTcpClient) onDisconnected(sender *dnet.ASyncTcpClient) {
	this.listeners.ForEach(func(val interface{}) {
		val.(I_CommListener).OnDisconnect(this)
	})
}

func (this *CommTcpClient) checkSend() {
	if this.flag == 0 {
		return
	}

	if !this.client.Connected {
		return
	}

	if this.nmea != nil {
		this.nmea.UpdateUTCTime()
		s := this.nmea.Encode() + "\r\n"
		this.client.PostSendBuffer([]byte(s))
	}

}

// =================================================================
func (this *CommTcpClient) onRecvClientBuffer(client *dnet.ASyncTcpClient, buffer []byte) {
	this.listeners.ForEach(func(val interface{}) {
		val.(I_CommListener).OnReceive(this, buffer, len(buffer))
	})
}

// =================================================================
func (this *CommTcpClient) Start() {
	this.client.Start()
	this.flag = 1
	this.taskTimer = time.AfterFunc(time.Second*10, this.doIntervalAction)
}

func (this *CommTcpClient) doIntervalAction() {
	if this.flag == 0 {
		return
	}

	if this.TimeOutSec > 0 {
		if this.client.CheckBreakConnectIfTimeOut(this.TimeOutSec) {
			utils.Log.Infof("[%s]超时无数据交互断开连接", this.client.RemoteAddress)
		}
	}

	this.checkSend()

	this.taskTimer = time.AfterFunc(time.Second*10, this.doIntervalAction)
}

func (this *CommTcpClient) GetFromAddr() string {
	return this.client.RemoteAddress
}

func (this *CommTcpClient) GetDisInfo() string {
	return this.client.LastDisMsg
}

func (this *CommTcpClient) GetSendBytes() int64 {
	return this.client.SendBytes()
}

func (this *CommTcpClient) Stop() {
	this.client.Stop()
	this.flag = 0
	if this.taskTimer != nil {
		this.taskTimer.Stop()
		this.taskTimer = nil
	}
}

func (this *CommTcpClient) Send(buf []byte, len int) int {
	if len <= 0 {
		return this.client.PostSendBuffer(buf)
	}
	return this.client.PostSendBuffer(buf[:len])
}

func (this *CommTcpClient) AddListener(event I_CommListener) {
	if this.listeners.Exists(event) {
		utils.Log.Warn("I_CommListener已经存在请勿重复侦听")
		return
	}
	this.listeners.Add(event)
}

func (this *CommTcpClient) RemoveListener(event I_CommListener) {
	this.listeners.Remove(event)
}
